import { _decorator, Component, Node, Animation } from "cc"
import { ItemBase } from "./itemBase"
import { GlobalData } from "../GlobalData"
import { util } from "../util/util"
import { sp } from "cc"
import { constant } from "../framework/constant"
import { Vec3 } from "cc"
import { ClientEvent } from "../framework/ClientEvent"
import { UITransform } from "cc"
import { AudioManager } from "../framework/AudioManager"
import { Tween } from "cc"
const { ccclass, property } = _decorator

@ccclass("Monster")
export class Monster extends ItemBase {
  protected goldDrop: number = 0

  protected animation: Animation = null

  protected nAttAckTarget: Node = null

  protected attackBefore:number = 0

  protected onLoad(): void {
    this.animation = this.node.getChildByName("animation").getComponent(Animation)
  }

  start() {
    this.playAnimation(constant.MONSTER_ANI_TYPE.WALK, true)
    this.rScale = Math.abs(this.node.scaleX)
  }



  init(monsterType: string) {
    this.isEnemy = true
    const data: any = GlobalData.instance.monsterData[monsterType]
    this.maxHp = constant.arrMonsterHp[GlobalData.instance.curLevel]//data.hp
    this.currHp = this.maxHp
    this.sName = data.name
    this.currAttack = data.attack
    this.attackScope = data.attackScope
    this.beAttackScope = data.beAttackScope
    this.moveSpeed = constant.monsterMoveSpeed[GlobalData.instance.curLevel]
    this.attackSpeed = data.attackSpeed
    this.goldDrop = constant.arrMonsterMoney[GlobalData.instance.curLevel]
    this.node.scaleX = Math.abs(this.node.scaleX)
    this.attackBefore = 0.2
  }

  protected numAttackBefore: number = 0
  protected numAttackCd: number = 0
  update(deltaTime: number) {
    // return
    if (!this.node || !this.node.isValid || this.isDie) return
    if (!GlobalData.instance.getGameState()){
      this.playAnimation(constant.MONSTER_ANI_TYPE.IDLE, true)
      return
    }

    /**攻击前奏 */
    if (this.isAttackAction) {
      this.numAttackBefore += deltaTime
      if (this.numAttackBefore >= this.attackBefore) {
        this.isAttackAction = false
        this.attackTarget()
      }
    }

    /**攻击cd */
    if (this.isAttackCd) {
      this.numAttackCd += deltaTime
      if(this.numAttackCd >= this.getAttackSpeed()){
        this.isAttackCd = false
        this.endAttackTarget()
      }
      return
    }



    const viewScope: number = 200
    this.nAttAckTarget = this.findTargetToAttack()
    if (this.nAttAckTarget) {
      let dis = util.getTwoPosXYLength(
        this.node.positionX,
        this.node.positionY,
        this.nAttAckTarget.positionX,
        this.nAttAckTarget.positionY
      )
      if (dis < this.attackScope) {
        //进入攻击范围
        this.isAttackCd = true
        this.playAnimation(constant.MONSTER_ANI_TYPE.ATTACK, false)
        this.startAttAckTarget()
      } else if (Math.abs(this.node.positionX - this.nAttAckTarget.positionX) < viewScope) {
        //进入视野范围
        this.movetoTargetPos(this.nAttAckTarget.getPosition(), deltaTime)
        this.playAnimation(constant.MONSTER_ANI_TYPE.WALK, true)
      } else {
        this.node.positionX -= this.getCurrMoveSpeed() * deltaTime
        this.playAnimation(constant.MONSTER_ANI_TYPE.WALK, true)
      }
    }
  }

  // 到达攻击点，寻找最近的目标
  protected findTargetToAttack(): Node {
    if (GlobalData.instance.arrNodePlayerRole.length > 0) {
      let disAttack: number = 0
      let nodeAttack: Node = null
      for (let i: number = 0; i < GlobalData.instance.arrNodePlayerRole.length; i++) {
        const node = GlobalData.instance.arrNodePlayerRole[i]
        const dis = util.getTwoPosXYLength(this.node.positionX, this.node.positionY, node.positionX, node.positionY)
        if (disAttack === 0 || disAttack > dis) {
          disAttack = dis
          nodeAttack = node
        }
      }
      return nodeAttack
    }

    return null
  }
  /**朝着目标移动 */
  movetoTargetPos(targetPos: Vec3, deltaTime: number) {
    //朝攻击目标移动
    const selfPos = this.node.getPosition()
    let directionX = targetPos.x - selfPos.x
    let directionY = targetPos.y - selfPos.y
    // 计算距离（用于判断是否到达目标）
    let distance = Math.sqrt(directionX * directionX + directionY * directionY)
    directionX /= distance
    directionY /= distance
    // 根据移动速度移动箭头
    this.node.setPosition(
      this.node.positionX + directionX * this.getCurrMoveSpeed() * deltaTime,
      this.node.positionY + directionY * this.getCurrMoveSpeed() * deltaTime
    )
  }

  protected getCurrMoveSpeed() {
    let speed = constant.monsterMoveSpeed[GlobalData.instance.curLevel]
    if(0 == GlobalData.instance.numMonsterSlow){
      speed = 0.2 * speed
    }
    // else if(1 == GlobalData.instance.numMonsterSlow){
    //   speed = 0.7 * speed
    // }
    return constant.SPEED_SCALE * speed
  }

  protected animationName: string = ""
  protected callbackAnimate: (...args: any[]) => void
  /**
   * 播放玩家帧动画
   */
  public playAnimation(animationName: string, loop: boolean = true, callback?: (...args: any[]) => void) {
    // return
    if (this.animationName == animationName && loop) return
    this.animationName = animationName
    this.animation.play(animationName)
  }

  startAttAckTarget() {
    this.isAttackAction = true
    this.isAttackCd = true
    this.numAttackBefore = 0
    this.numAttackCd = 0
  }

  attackTarget() {
    if (this.nAttAckTarget && this.nAttAckTarget.isValid) {
      const item: ItemBase = this.nAttAckTarget.getComponent(ItemBase)
      if (item && !item.isDie) {
        item.onBeAttack(constant.arrMonsterAttack[GlobalData.instance.curLevel])
      }
    }
  }
  endAttackTarget() {
    this.isAttackCd = false
  }

  protected getAttackSpeed() {
    return this.attackSpeed
  }

  protected changeHp(value: number) {
    if (!GlobalData.instance.isGameStart || GlobalData.instance.isGameOver || GlobalData.instance.isGamePause) return
    value = Math.round(value)
    this.currHp -= value
    ClientEvent.emit("onInitDamage", this.node.getPosition(), value)
    this.onChangeHp(this.currHp)
  }
  protected onChangeHp(hp: number) {
    // return
    if (!this.maxHp) return
    this.currHp = hp
    if (this.currHp > this.maxHp) {
      this.currHp = this.maxHp
    }

    if (this.currHp <= 0) {
      this.currHp = 0
      this.isDie = true
    }
  }

  protected showDie(): void {
    const indexOf = GlobalData.instance.arrNodeMonster.indexOf(this.node)
    if (indexOf !== -1) {
      GlobalData.instance.arrNodeMonster.splice(indexOf, 1)
      ClientEvent.emit("onMonsterDie", this.goldDrop, this.node.getPosition())
    }
    this.playAnimation(constant.MONSTER_ANI_TYPE.DIE, false)
    new Tween(this.node)
      .to(0.3, { alpha: 0 })
      .call(() => {
        this.onDestroySelf()
      })
      .start()
    AudioManager.instance.playEffect("sm_monster_die")
  }

  onBeAttack(attack: number, nodeBeAttack?: Node): void {
    ClientEvent.emit("onMonsterBeAttackEffect", new Vec3(this.node.positionX, this.node.positionY))
    super.onBeAttack(attack, nodeBeAttack)
  }

  protected onDestroySelf(): void {
    this.node.destroy()
    this.destroy()
  }
}
